//command pattern 请求模式
//将请求封装为一个对象，从而使你可用不同的请求对客户进行参数化
//实现请求排队、记录请求日志以及支持可撤销的操作
#include <iostream>
#include <memory>
#include <string>
#include <list>
//实际的执行操作的类,可以执行多种操作
class Baker
{
public:
    using ptr=std::shared_ptr<Baker>;
    void bakeMutton()
    {
        std::cout<<"正宗的新疆羊肉串嘞~"<<std::endl;
    }
    void bakeFatPork()
    {
        std::cout<<"五花肉正在兹拉兹拉的冒油"<<std::endl;
    }
    void bakeFish()
    {
        std::cout<<"海的味道，我知道！"<<std::endl;
    }
    void bakeWings()
    {
        std::cout<<"孜然鸡翅膀呀,我最爱!"<<std::endl;
    }
};
//将一个对象中的多种类似的行为，拆分为多个命令类，他们都继承一个同一个虚类
class Command
{
public:
    using ptr=std::shared_ptr<Command>;
    Command(Baker::ptr baker):m_baker(baker){}
    void setBaker(Baker::ptr baker)
    {
        m_baker=baker;
    }
    virtual void excute()=0;
protected:
    Baker::ptr m_baker;
};

class BakeMutton:public Command
{
public:
    using ptr=std::shared_ptr<BakeMutton>;
    BakeMutton(Baker::ptr baker):Command(baker){}
    virtual void excute()
    {
        Command::m_baker->bakeMutton();
    }
};

class BakeFatPork:public Command
{
public:
    using ptr=std::shared_ptr<BakeFatPork>;
    BakeFatPork(Baker::ptr baker):Command(baker){}
    virtual void excute()
    {
        Command::m_baker->bakeFatPork();
    }
};

class BakeWings:public Command
{
public:
    using ptr=std::shared_ptr<BakeWings>;
    BakeWings(Baker::ptr baker):Command(baker){}
    virtual void excute()
    {
        Command::m_baker->bakeWings();
    }
};

class BakeFish:public Command
{
public:
    using ptr=std::shared_ptr<BakeFish>;
    BakeFish(Baker::ptr baker):Command(baker){}
    virtual void excute()
    {
        Command::m_baker->bakeFish();
    }
};
//waitress中存储命令的合集  用于添加、删除或者判断不同的命令执行；
class Waitress
{
public:
    using ptr=std::shared_ptr<Waitress>;
    void addCommand(Command::ptr command)
    {
        m_commands.push_back(command);
    }
    void removeCommand(Command::ptr command)
    {
        m_commands.remove(command);
    }
    void logCommand()
    {
        std::cout<<"你点的烧烤如下:"<<std::endl;
        for(const auto& item:m_commands){
            item->excute();
        }
    }
private:
    std::list<Command::ptr> m_commands;
};

int main(int argc, char** argv)
{
    Baker::ptr baker(new Baker);
    BakeFish::ptr bakeFish(new BakeFish(baker));
    BakeMutton::ptr bakeButton(new BakeMutton(baker));
    BakeFatPork::ptr bakePork(new BakeFatPork(baker));
    BakeWings::ptr bakeWings(new BakeWings(baker));
    Waitress::ptr waitress(new Waitress);
    std::cout<<"小杜，咱们吃点烤鱼和烤羊肉吧！"<<std::endl;
    waitress->addCommand(bakeFish);
    waitress->addCommand(bakeButton);
    waitress->logCommand();
    return 0;
}